using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace SnarlGMailNotifier.Classes.Animations
{
    public class SlideAnimation : AnimationBase
    {
        System.Timers.Timer m_timer = null;

        private SlideDirection m_direction;
        private SlideType m_type;
        private Size m_desiredWindowSize;
        private Point m_desiredWindowLocation;

        private Size m_oldWindowSize;
        private Point m_oldWindowLocation;

        public override event Animations.AnimationFinishedDelegate AnimationFinished;
        public override event AnimationBase.AnimationStepChangedDelegate AnimationStepChanged;

        public enum SlideDirection
        {
            Left,
            Right,
            Top,
            Bottom
        }

        public enum SlideType
        { 
            SlideIn,
            SlideOut
        }
        
        public SlideAnimation(int duration, SlideType type, SlideDirection direction)
            : base(duration)
        {
            this.m_type = type;
            this.m_direction = direction;
        }

        public override void StartAnimation(Form form)
        {
            if (this.m_type == SlideType.SlideIn)
            {
                this.m_desiredWindowSize = form.Size;
                this.m_desiredWindowLocation = form.Location;
            }
            else if(this.m_type == SlideType.SlideOut)
            {
                this.m_oldWindowSize = form.Size;
                this.m_oldWindowLocation = form.Location;

                this.m_desiredWindowSize = new Size(0, 0);

                switch (this.m_direction)
                { 
                    case SlideDirection.Bottom:
                        this.m_desiredWindowLocation = new Point(form.Left, form.Bottom);
                        break;

                    case SlideDirection.Top:
                        this.m_desiredWindowLocation = new Point(form.Left, form.Top);
                        break;

                    case SlideDirection.Left:
                        this.m_desiredWindowLocation = new Point(form.Left, form.Top);
                        break;

                    case SlideDirection.Right:
                        this.m_desiredWindowLocation = new Point(form.Right, form.Top);
                        break;
                }
            }

            this.m_formToAnimate = form;

            this.m_datStartTime = DateTime.Now;
            this.m_datStopTime = this.m_datStartTime.AddMilliseconds(this.m_intDuration);
            
            this.m_timer = new System.Timers.Timer(1.0);
            this.m_timer.Elapsed += new System.Timers.ElapsedEventHandler(m_timer_Elapsed);
            this.m_timer.Start();
            
            form.Visible = true;
        }

        private void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            double currentPercent = this.CalculateCurrentStepPercent(
                this.m_datStartTime, 
                this.m_datStopTime, 
                DateTime.Now);

            if (currentPercent > 0.0 && currentPercent < 1.0)
            {
                if (this.m_type == SlideType.SlideIn)
                {
                    switch (this.m_direction)
                    {
                        case SlideDirection.Left:
                            this.SetWidth(this.m_formToAnimate, (int)((double)this.m_desiredWindowSize.Width * currentPercent));
                            this.SetLeft(this.m_formToAnimate, this.m_desiredWindowLocation.X + this.m_desiredWindowSize.Width - this.m_formToAnimate.Width);
                            break;

                        case SlideDirection.Bottom:
                            this.SetHeight(this.m_formToAnimate, (int)((double)this.m_desiredWindowSize.Height * currentPercent));
                            break;

                        case SlideDirection.Right:
                            this.SetWidth(this.m_formToAnimate, (int)((double)this.m_desiredWindowSize.Width * currentPercent));
                            break;

                        case SlideDirection.Top:
                            this.SetHeight(m_formToAnimate, (int)((double)this.m_desiredWindowSize.Height * currentPercent));
                            this.SetTop(this.m_formToAnimate, this.m_desiredWindowLocation.Y + this.m_desiredWindowSize.Height - this.m_formToAnimate.Height);
                            break;
                    }
                }
                else if (this.m_type == SlideType.SlideOut)
                {
                    switch (this.m_direction)
                    {
                        case SlideDirection.Left:
                            this.SetWidth(this.m_formToAnimate, (int)((double)this.m_oldWindowSize.Width * (1.0 - currentPercent)));
                            break;

                        case SlideDirection.Bottom:
                            this.SetHeight(this.m_formToAnimate, (int)((double)this.m_oldWindowSize.Height * (1.0 - currentPercent)));
                            this.SetTop(this.m_formToAnimate, this.m_desiredWindowLocation.Y + this.m_desiredWindowSize.Height - this.m_formToAnimate.Height);
                            break;

                        case SlideDirection.Right:
                            this.SetWidth(this.m_formToAnimate, (int)((double)this.m_oldWindowSize.Width * (1.0 - currentPercent)));
                            this.SetLeft(this.m_formToAnimate, this.m_desiredWindowLocation.X + this.m_desiredWindowSize.Width - this.m_formToAnimate.Width);
                            break;

                        case SlideDirection.Top:
                            this.SetHeight(m_formToAnimate, (int)((double)this.m_oldWindowSize.Height * (1.0 - currentPercent)));
                            break;
                    }
                }

                if (this.AnimationStepChanged != null)
                    this.AnimationStepChanged(this, new AnimationStepEventArgs(currentPercent));
            }
            else if (currentPercent >= 1.0)
            {
                if (this.m_type == SlideType.SlideIn)
                {
                    this.SetTop(this.m_formToAnimate, this.m_desiredWindowLocation.Y);
                    this.SetLeft(this.m_formToAnimate, this.m_desiredWindowLocation.X);
                    this.SetHeight(this.m_formToAnimate, this.m_desiredWindowSize.Height);
                    this.SetWidth(this.m_formToAnimate, this.m_desiredWindowSize.Width);
                }
                else if (this.m_type == SlideType.SlideOut)
                {
                    this.SetVisible(this.m_formToAnimate, false);

                    this.SetTop(this.m_formToAnimate, this.m_oldWindowLocation.Y);
                    this.SetLeft(this.m_formToAnimate, this.m_oldWindowLocation.X);
                    this.SetHeight(this.m_formToAnimate, this.m_oldWindowSize.Height);
                    this.SetWidth(this.m_formToAnimate, this.m_oldWindowSize.Width);
                }

                if (this.AnimationFinished != null)
                    this.AnimationFinished(this, EventArgs.Empty);

                this.m_timer.Elapsed -= new System.Timers.ElapsedEventHandler(m_timer_Elapsed);
            }
        }
    }
}
